package com.franklin.ideaplugin.maphelper.utils;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.franklin.ideaplugin.api.utils.ClassUtils;
import com.franklin.ideaplugin.api.utils.psi.PsiClassUtils;
import com.franklin.ideaplugin.api.utils.psi.PsiExpressionUtils;
import com.franklin.ideaplugin.maphelper.beans.colmember.IColMember;
import com.franklin.ideaplugin.maphelper.beans.colmember.StringColMember;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;

import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Ye Junhui
 * @since 2024/3/20
 */
public class FastJsonUtils {

    /**
     * fastjson-object类型
     */
    public final static Set<String> FAST_JSON_OBJECT_CLASSES = Sets.newHashSet(
            "com.alibaba.fastjson.JSONObject",
            "com.alibaba.fastjson2.JSONObject"
    );

    /**
     * fastjson-array类型
     */
    public final static Set<String> FAST_JSON_ARRAY_CLASSES = Sets.newHashSet(
            "com.alibaba.fastjson.JSONArray",
            "com.alibaba.fastjson2.JSONArray"
    );

    /**
     * fastjson类型
     */
    public final static Set<String> FAST_JSON_CLASSES = Sets.newHashSet(
            "com.alibaba.fastjson.JSON",
            "com.alibaba.fastjson2.JSON"
    );

    /**
     * 寻找JSON字符串的成员
     *
     * @param psiMethodCallExpression
     * @param parseMethodName
     * @return
     */
    public static List<IColMember> findJsonObjectStringMembers(
            PsiMethodCallExpression psiMethodCallExpression,
            String parseMethodName
    ) {
        List<IColMember> result = Lists.newArrayList();
        if (!isJsonParseMethod(psiMethodCallExpression, parseMethodName)) {
            return result;
        }

        PsiExpressionList psiExpressionList = PsiTreeUtil.findChildOfType(psiMethodCallExpression, PsiExpressionList.class);
        //将代码转成JSON字符串
        PsiExpression psiExpression = psiExpressionList.getExpressions()[0];
        Collection<PsiLiteralExpression> psiLiteralExpressions = PsiTreeUtil.collectElementsOfType(psiExpression, PsiLiteralExpression.class);
        String jsonString = psiLiteralExpressions.stream()
                .map(PsiExpressionUtils::getCleanText)
                .collect(Collectors.joining(""));

        //调用类
        PsiClass jsonClass = psiMethodCallExpression.resolveMethod().getContainingClass();

        try {
            Method declaredMethod = JSON.class.getDeclaredMethod(parseMethodName, String.class);
            declaredMethod.setAccessible(true);
            Object object = declaredMethod.invoke(JSON.class, jsonString);
            return resolveJsonStringMembers(jsonClass.getQualifiedName(), object);
        } catch (Exception e) {

        }

        return result;
    }


    /**
     * 解析json成员
     * @param jsonClass
     * @param json
     * @return
     */
    public static List<IColMember> resolveJsonStringMembers(String jsonClass,Object json){
        if (Objects.isNull(json)){
            return Lists.newArrayList();
        }
        if (json instanceof JSONObject){
            return resolveJsonObjectStringMembers(jsonClass, (JSONObject) json);
        }else if (json instanceof JSONArray){
            return resolveJsonArrayStringMembers(jsonClass,(JSONArray) json);
        }else if (json instanceof String){
            String jsonString = (String) json;
            if (JSON.isValid(jsonString)){
                return resolveJsonStringMembers(jsonClass,JSON.parse(jsonString));
            }
        }
        return Lists.newArrayList();
    }

    /**
     * 是否是JSONObject
     * @param jsonString
     * @return
     */
    public static boolean isValidJsonObject(String jsonString){
        try {
            JSONObject jsonObject = JSON.parseObject(jsonString);
            return Objects.nonNull(jsonObject);
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 是否是JSONArray
     * @param jsonString
     * @return
     */
    public static boolean isValidJsonArray(String jsonString){
        try {
            JSONArray jsonArray = JSON.parseArray(jsonString);
            return Objects.nonNull(jsonArray);
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 解析JSONObject的成员
     * @param jsonClass
     * @param jsonObject
     * @return
     */
    public static List<IColMember> resolveJsonObjectStringMembers(String jsonClass,JSONObject jsonObject){
        List<IColMember> result = Lists.newArrayList();
        jsonObject.forEach((k,v) -> {
            String valueClass = v.getClass().getName();
            if (v instanceof JSONObject){
                valueClass = getJsonClass(jsonClass,FAST_JSON_OBJECT_CLASSES);
            }else if (v instanceof JSONArray){
                valueClass = getJsonClass(jsonClass,FAST_JSON_ARRAY_CLASSES);
            }

            //封装数据
            StringColMember stringColMember = new StringColMember();
            stringColMember.setKeyText(String.format("\"%s\"", k));
            stringColMember.setValueText("json string");
            stringColMember.setValueClass(valueClass);
            stringColMember.setValue(v);

            result.add(stringColMember);
        });

        return result;
    }

    /**
     * 解析JSONObject的成员
     * @param jsonClass
     * @param jsonArray
     * @return
     */
    public static List<IColMember> resolveJsonArrayStringMembers(String jsonClass,JSONArray jsonArray){
        return jsonArray.stream()
                .map(v -> {
                    String valueClass = v.getClass().getName();
                    if (v instanceof JSONObject){
                        valueClass = getJsonClass(jsonClass,FAST_JSON_OBJECT_CLASSES);
                    }else if (v instanceof JSONArray){
                        valueClass = getJsonClass(jsonClass,FAST_JSON_ARRAY_CLASSES);
                    }

                    //封装数据
                    StringColMember stringColMember = new StringColMember();
                    stringColMember.setKeyText("jsonArray");
                    stringColMember.setValueText("json string");
                    stringColMember.setValueClass(valueClass);
                    stringColMember.setValue(v);

                    return stringColMember;
                })
                .collect(Collectors.toList());
    }

    /**
     * 获取JSON类
     * @param jsonClass
     * @param fastJsonClasses
     * @return
     */
    public static String getJsonClass(PsiClass jsonClass,Set<String> fastJsonClasses){
        return getJsonClass(jsonClass.getQualifiedName(),fastJsonClasses);
    }

    /**
     * 获取JSON类
     * @param className
     * @param fastJsonClasses
     * @return
     */
    public static String getJsonClass(String className,Set<String> fastJsonClasses){
        String classPackage = ClassUtils.getClassPackage(className);
        for (String fastJsonObjectClass : fastJsonClasses) {
            if (fastJsonObjectClass.startsWith(classPackage)){
                return fastJsonObjectClass;
            }
        }
        throw new IllegalArgumentException("没找到类");
    }

    /**
     * 是否是json解析方法
     *
     * @param psiMethodCallExpression
     * @param parseMethodName
     * @return
     */
    public static boolean isJsonParseMethod(
            PsiMethodCallExpression psiMethodCallExpression,
            String parseMethodName
    ) {
        if (Objects.isNull(psiMethodCallExpression)) {
            return false;
        }
        //方法
        PsiMethod psiMethod = psiMethodCallExpression.resolveMethod();
        if (Objects.isNull(psiMethod)) {
            return false;
        }
        if (!psiMethod.getName().equals(parseMethodName)) {
            return false;
        }

        //类
        PsiClass containingClass = psiMethod.getContainingClass();
        if (!isJsonClass(containingClass)) {
            return false;
        }

        //返回值
        PsiType returnType = psiMethod.getReturnType();
        if (!PsiClassType.class.isInstance(returnType)) {
            return false;
        }
        PsiClassType psiClassType = (PsiClassType) returnType;
        PsiClass psiClass = psiClassType.resolve();
        if (Objects.isNull(psiClass)) {
            return false;
        }
        String qualifiedName = psiClass.getQualifiedName();
        if (!FAST_JSON_OBJECT_CLASSES.contains(qualifiedName) && !FAST_JSON_ARRAY_CLASSES.contains(qualifiedName)) {
            return false;
        }

        //校验参数
        PsiParameterList parameterList = psiMethod.getParameterList();
        if (parameterList.getParametersCount() < 1) {
            return false;
        }
        PsiParameter parameter = parameterList.getParameter(0);
        if (Objects.isNull(parameter)) {
            return false;
        }

        //校验参数类型
        PsiType parameterType = parameter.getType();
        if (!PsiClassType.class.isInstance(parameterType)) {
            return false;
        }
        PsiClassType paramClassType = (PsiClassType) parameterType;
        PsiClass paramClass = paramClassType.resolve();
        PsiClass stringClass = PsiClassUtils.findPsiClass(psiClass.getProject(), String.class);
        if (!PsiClassUtils.isInheritorOrEquals(stringClass, paramClass)) {
            return false;
        }

        //参数
        PsiExpressionList psiExpressionList = PsiTreeUtil.findChildOfType(psiMethodCallExpression, PsiExpressionList.class);
        if (Objects.isNull(psiExpressionList)) {
            return false;
        }
        if (psiExpressionList.getExpressionCount() < 1) {
            return false;
        }

        return true;
    }

    /**
     * 是否是JSON 类
     *
     * @param psiClass
     * @return
     */
    public static boolean isJsonClass(PsiClass psiClass) {
        if (Objects.isNull(psiClass)) {
            return false;
        }
        for (String fastJsonClass : FAST_JSON_CLASSES) {
            PsiClass jsonClass = PsiClassUtils.findPsiClass(psiClass.getProject(), fastJsonClass);
            if (PsiClassUtils.isInheritorOrEquals(jsonClass, psiClass)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 是否是JSONObject 类
     *
     * @param psiClass
     * @return
     */
    public static boolean isJsonObjectClass(PsiClass psiClass) {
        if (Objects.isNull(psiClass)) {
            return false;
        }
        for (String fastJsonClass : FAST_JSON_OBJECT_CLASSES) {
            PsiClass jsonClass = PsiClassUtils.findPsiClass(psiClass.getProject(), fastJsonClass);
            if (PsiClassUtils.isInheritorOrEquals(jsonClass, psiClass)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 是否是JSONArrau 类
     *
     * @param psiClass
     * @return
     */
    public static boolean isJsonArrayClass(PsiClass psiClass) {
        if (Objects.isNull(psiClass)) {
            return false;
        }
        for (String fastJsonClass : FAST_JSON_ARRAY_CLASSES) {
            PsiClass jsonClass = PsiClassUtils.findPsiClass(psiClass.getProject(), fastJsonClass);
            if (PsiClassUtils.isInheritorOrEquals(jsonClass, psiClass)) {
                return true;
            }
        }
        return false;
    }
}
